import { Action, getModule, Module, Mutation, VuexModule } from 'vuex-module-decorators';
import { AuthModel } from '@/models/auth.model';
import http from '@/plugins/http';
import store from '@/store';
import router, { resetRouter, routes } from '@/router';
import { DialogModule } from '@/store/dialog';
import { DrawerModule } from '@/store/drawer';
import { AccountLogin, getCurrentAccount } from '@/services/account.service';
import { AccountLoginModel } from '@/models/account.login.model';
import { getTimestamp } from '@/.ke/utils';
import log from 'loglevel';

const checkPermission = (policy: string, policys: string[]): boolean => {
    if (!policys || policys.length == 0) {
        // 前台没有任何节点时直接为超管
        // console.log('po', policy, policys)
        return true;
    }
    if (!policy.includes(',')) {
        return policys.includes(policy);
    }
    let tmps = policy.split(',');
    for (let tmp of tmps) {
        if (!policys.includes(policy)) {
            return false;
        }
    }
    return true;
}

/**
 * 获取令牌
 */
const getToken = (): [string | null, number] => {
    const time = getTimestamp();
    const expire = Number(sessionStorage.getItem('login_expire'));
    const token = sessionStorage.getItem('login_token');
    if (expire <= time || !token) {
        return [null, 0];
    }
    return [token, expire];
}

/**
 * 设置令牌
 * @param token
 * @param expire_in
 */
const setToken = (token: string, expire_in: number) => {
    sessionStorage.setItem('login_token', token);

    sessionStorage.setItem('login_expire', (getTimestamp() + expire_in).toString());
}

@Module({ name: 'auth', dynamic: true, namespaced: true, store })
export default class AuthStore extends VuexModule {
    private $info = {} as any;
    private $certInfo: any = { tok: '', expire: 0 };
    private $isLogin: boolean = false;
    private $policys: string[] = [];
    private $403: string[] = [];
    private $routes: any[] = [];
    private $topHidden: string[] = [];

    /**
     * 登录用户资料
     */
    public get userinfo(): AuthModel {
        return this.$info ?? {};
    }

    /**
     * 登录令牌
     */
    public get token(): string | null {
        if (this.$certInfo.tok && this.$certInfo.expire < getTimestamp()) {
            return null;
        }
        return this.$certInfo.tok;
    }


    @Mutation
    public setToken(info: { tok: string, expire: number }) {
        this.$certInfo = info;
        this.$isLogin = true;
    }


    /**
     * 是否已登录
     */
    public get isLogin(): boolean {
        if (!this.$certInfo.tok) {
            return false;
        }
        return this.$isLogin;
    }


    public get policys(): string[] {
        return this.$policys;
    }

    /**
     * 隐藏的头部菜单
     */
    public get topHidden(): string[] {
        return this.$topHidden;
    }


    /**
     * 判断是否拥有某个权限
     */
    public get hasAuth(): (policy: string) => boolean {
        return (policy: string): boolean => checkPermission(policy, this.$policys);
    }


    /**
     * 更新用户资料，自动合并旧数据
     * @param info
     */
    @Mutation
    public updateInfo(info: AuthModel) {
        this.$info = { ...this.$info, ...info };
    }


    /**
     * 更新权限策略
     * @param data
     */
    @Mutation
    public updatePolicy(data: string[]) {
        this.$policys = data;
    }

    public get routes(): any[] {
        return [{
            path: '',
            name: 'Index',
            module: 'index',
            meta: {
                title: '首页'
            },
        }, ...this.$routes];
    }


    @Mutation
    private updateRoutes(routes: any) {
        let map: {[key: string]: number} = {};

        log.info('policy', this.$policys);
        const filterRoutes = (routes: any) => {
            let list: any[] = [];
            try {
                routes.map((route: any) => {
                    let tmp = { ...route };
                    // if (route.hidden) {
                    //     return false;
                    // }
                    if (route.module) {
                        if (!map[route.module]) map[route.module] = 0;
                    }
                    if (tmp.meta?.auth && !checkPermission(tmp.meta?.auth, this.$policys)) {
                        return;
                    }
                    if (route.module) {
                        map[route.module]++;
                    }

                    if (route.children) {
                        tmp.children = filterRoutes(tmp.children);
                    }
                    list.push(tmp);
                });
            } catch (e) {
                log.error(e);
            }

            return list;
        }
        routes = filterRoutes(routes);

        this.$topHidden = [];
        for (let key in map) {
            if (map[key] === 0) {
                this.$topHidden.push(key);
            }
        }

        resetRouter();
        this.$routes = routes;

        router.addRoutes([
            ...this.$routes,
            {
                path: '*',
                component: () => import('@/views/public/404.vue')
            }
        ]);
    }


    /**
     * 被禁止访问的页面
     */
    public get banPages(): string[] {
        return this.$403;
    }


    /**
     * 禁止某个页面访问，显示403页面
     * @param page.route 路由名
     */
    @Mutation
    public banPage(page: any) {
        if (!this.$403.includes(page.route)) {
            this.$403.push(page.route);
        }
    }


    /**
     * 让某个页面可以访问
     * @param page.route 路由名
     */
    @Mutation
    public canPage(page: any) {
        const idx = this.$403.indexOf(page.route);
        if (idx > -1) {
            this.$403.splice(idx, 1);
        }
    }

    /**
     * 注销登陆
     */
    @Action
    public logout() {
        DialogModule.close();
        DrawerModule.close();
        let query: any = {};
        if (!router.currentRoute.query.redirect) {
            query.redirect = router.currentRoute.fullPath;
        }
        http.delete('admin/account/logout')
            .finally(() => {
                router.push({
                    name: 'login',
                    query,
                });
            })
    }

    /**
     * 从服务器获取用户资料
     */
    @Action
    getInfo() {
        return new Promise((resolve, reject) => {
            const [token, expire] = getToken();

            if (!token) {
                reject(false);
                return;
            }
            this.context.commit('setToken', {
                tok: token,
                expire: expire,
            });

            getCurrentAccount()
                .then(result => {
                    this.context.commit('updateInfo', result.info);
                    this.context.commit('updatePolicy', result.policys);
                    this.context.commit('updateRoutes', routes);

                    resolve(true);
                })
                .catch(() => {
                    reject(false);
                })
        })
   }

    /**
     * 登陆
     * @param {AccountLoginModel} form
     */
    @Action
    login(form: AccountLoginModel) {
        return new Promise(resolve => {
            AccountLogin(form)
                .then(result => {
                    setToken(result.data.access_token, result.data.expire_in);
                    this.context.commit('setToken', {
                        tok: result.data.access_token,
                        expire: result.data.expire_in + getTimestamp(),
                    });

                    this.context.commit('updateInfo', result.data.info);
                    this.context.commit('updatePolicy', result.data.policys);
                    this.context.commit('updateRoutes', routes);
                    console.log('result', result);

                    resolve(true);
                })
                .catch(err => {
                    resolve(false);
                })
        })
    }

}

export const AuthModule = getModule(AuthStore);
